<!DOCTYPE html>
<html>
<head>
    <title>Thermodynamics Diagram</title>
</head>
<body>
<canvas id="physics-diagram" width="600" height="300" style="border: 1px solid #ccc;"></canvas>
<script>
    const canvas = document.getElementById('physics-diagram');
    const ctx = canvas.getContext('2d');

    // --- Configuration ---
    const config = {
        boxWidth: 160,
        boxHeight: 90,
        leftBoxX: 50,
        rightBoxX: 390,
        boxY: 40,
        baseFont: '18px Arial',
        superFont: '12px Arial',
        arrowHeadSize: 10,
        lineWidth: 1,
        textColor: 'black'
    };

    ctx.lineWidth = config.lineWidth;
    ctx.strokeStyle = config.textColor;
    ctx.fillStyle = config.textColor;

    // --- Helper Functions ---

    /**
     * Calculates the total width of a text string composed of multiple parts (for superscripts).
     * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
     * @param {Array<Object>} parts - Array of text parts, e.g., [{text: '10'}, {text: '5', script: 'super'}].
     * @param {string} baseFont - The font for normal text.
     * @param {string} superFont - The font for superscript text.
     * @returns {number} The total width of the text.
     */
    function calculateRichTextWidth(ctx, parts, baseFont, superFont) {
        let totalWidth = 0;
        parts.forEach(part => {
            ctx.font = (part.script === 'super') ? superFont : baseFont;
            totalWidth += ctx.measureText(part.text).width;
        });
        return totalWidth;
    }

    /**
     * Draws a text string with superscripts, horizontally centered at a given point.
     * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
     * @param {Array<Object>} parts - Array of text parts.
     * @param {number} centerX - The x-coordinate to center the text around.
     * @param {number} y - The y-coordinate for the baseline of the main text.
     * @param {string} baseFont - The font for normal text.
     * @param {string} superFont - The font for superscript text.
     */
    function drawRichText(ctx, parts, centerX, y, baseFont, superFont) {
        const totalWidth = calculateRichTextWidth(ctx, parts, baseFont, superFont);
        let currentX = centerX - totalWidth / 2;

        ctx.textAlign = 'left';
        ctx.textBaseline = 'middle';

        parts.forEach(part => {
            const isSuper = part.script === 'super';
            ctx.font = isSuper ? superFont : baseFont;
            const yPos = isSuper ? y - 7 : y; // Vertical offset for superscript
            ctx.fillText(part.text, currentX, yPos);
            currentX += ctx.measureText(part.text).width;
        });
    }

    /**
     * Draws an arrowhead at a point, pointing in a given direction (angle).
     * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
     * @param {number} x - The x-coordinate of the arrowhead tip.
     * @param {number} y - The y-coordinate of the arrowhead tip.
     * @param {number} angle - The angle of the arrow direction in radians.
     * @param {number} size - The length of the arrowhead barbs.
     */
    function drawArrowHead(ctx, x, y, angle, size) {
        ctx.save();
        ctx.beginPath();
        ctx.translate(x, y);
        ctx.rotate(angle);
        ctx.moveTo(0, 0);
        ctx.lineTo(-size, -size / 2.5);
        ctx.moveTo(0, 0);
        ctx.lineTo(-size, size / 2.5);
        ctx.stroke();
        ctx.restore();
    }

    // --- Main Drawing Logic ---

    // 1. Draw Boxes
    ctx.strokeRect(config.leftBoxX, config.boxY, config.boxWidth, config.boxHeight);
    ctx.strokeRect(config.rightBoxX, config.boxY, config.boxWidth, config.boxHeight);

    // 2. Draw Text in Boxes
    const leftBoxCenterX = config.leftBoxX + config.boxWidth / 2;
    const rightBoxCenterX = config.rightBoxX + config.boxWidth / 2;
    const line1Y = config.boxY + 22;
    const line2Y = config.boxY + 47;
    const line3Y = config.boxY + 72;

    // Left Box Text
    const textL1 = [{ text: '2.30 × 10' }, { text: '-3', script: 'super' }, { text: ' m' }, { text: '3', script: 'super' }];
    const textL2 = [{ text: '2.60 × 10' }, { text: '5', script: 'super' }, { text: ' Pa' }];
    drawRichText(ctx, textL1, leftBoxCenterX, line1Y, config.baseFont, config.superFont);
    drawRichText(ctx, textL2, leftBoxCenterX, line2Y, config.baseFont, config.superFont);
    ctx.font = config.baseFont;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText('180 K', leftBoxCenterX, line3Y);

    // Right Box Text
    const textR1 = [{ text: '3.80 × 10' }, { text: '-3', script: 'super' }, { text: ' m' }, { text: '3', script: 'super' }];
    const textR2 = [{ text: '2.60 × 10' }, { text: '5', script: 'super' }, { text: ' Pa' }];
    drawRichText(ctx, textR1, rightBoxCenterX, line1Y, config.baseFont, config.superFont);
    drawRichText(ctx, textR2, rightBoxCenterX, line2Y, config.baseFont, config.superFont);
    ctx.font = config.baseFont;
    ctx.fillText('T', rightBoxCenterX, line3Y);

    // 3. Draw Connecting Lines and Arrows
    const lineY = config.boxY + config.boxHeight / 2;
    const junctionX = config.leftBoxX + config.boxWidth + (config.rightBoxX - (config.leftBoxX + config.boxWidth)) / 2;
    const heatInputY = lineY + 90;

    // Main lines
    ctx.beginPath();
    // Line from left box to junction
    ctx.moveTo(config.leftBoxX + config.boxWidth, lineY);
    ctx.lineTo(junctionX, lineY);
    // Line from junction to right box
    ctx.moveTo(junctionX, lineY);
    ctx.lineTo(config.rightBoxX, lineY);
    // Vertical line for heat input
    ctx.moveTo(junctionX, heatInputY);
    ctx.lineTo(junctionX, lineY);
    ctx.stroke();
    
    // Arrowheads
    const arrow1X = config.leftBoxX + config.boxWidth + (junctionX - (config.leftBoxX + config.boxWidth)) / 2;
    const arrow2X = junctionX + (config.rightBoxX - junctionX) / 2;
    drawArrowHead(ctx, arrow1X, lineY, 0, config.arrowHeadSize); // Right-pointing arrow
    drawArrowHead(ctx, arrow2X, lineY, 0, config.arrowHeadSize); // Right-pointing arrow
    drawArrowHead(ctx, junctionX, lineY, -Math.PI / 2, config.arrowHeadSize); // Up-pointing arrow

    // 4. Draw Heat Input Text
    ctx.font = config.baseFont;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'top';
    ctx.fillText('980 J', junctionX, heatInputY + 8);

    // 5. Draw Figure Label
    ctx.font = '16px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';
    ctx.fillText('Fig. 2.1', canvas.width / 2, canvas.height - 10);

</script>
</body>
</html>